#include "serial_api.h"
 
 #include <windows.h>
 
 using namespace std;
 
 int TIMEOUT = 300;//1000;
 
 TTY::TTY() {
 	m_Handle = 0;
	
 }
 
 TTY::~TTY() {
 	Disconnect();
 }
 
 bool TTY::Connect(const string& port, int baudrate) {
 
 	Disconnect();
 
 	m_Handle =
 		CreateFile(
 		port.c_str(), 
 		GENERIC_READ | GENERIC_WRITE,
 		0,
 		NULL,
 		OPEN_EXISTING, 
 		FILE_ATTRIBUTE_NORMAL,
 		NULL);
 
 	if(m_Handle == (HANDLE)-1) {
 		m_Handle = 0;
 		//throw TTYException();
		return false;
 	}
 
 	SetCommMask(m_Handle, EV_RXCHAR);
	SetupComm(m_Handle,main_settings.dwInQueue,main_settings.dwOutQueue); //1500, 1500);
 
 	COMMTIMEOUTS CommTimeOuts;
 	CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
 	CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
	CommTimeOuts.ReadTotalTimeoutConstant = main_settings.l_TIMEOUT;
 	CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
	CommTimeOuts.WriteTotalTimeoutConstant = main_settings.l_TIMEOUT;//TIMEOUT;
 
 	if(!SetCommTimeouts(m_Handle, &CommTimeOuts)) {
 		m_Handle = 0;
		return false;
 		//throw TTYException();
 	}
 
 	DCB ComDCM;
 
 	memset(&ComDCM,0,sizeof(ComDCM));
 	ComDCM.DCBlength = sizeof(DCB);
 	GetCommState(m_Handle, &ComDCM);
 	ComDCM.BaudRate = DWORD(baudrate);
 	ComDCM.ByteSize = 8;
 	ComDCM.Parity = NOPARITY;
 	ComDCM.StopBits = ONESTOPBIT;
 	ComDCM.fAbortOnError = TRUE;
 	ComDCM.fDtrControl = DTR_CONTROL_DISABLE;
 	ComDCM.fRtsControl = RTS_CONTROL_DISABLE;
 	ComDCM.fBinary = TRUE;
 	ComDCM.fParity = FALSE;
 	ComDCM.fInX = ComDCM.fOutX = FALSE;
 	ComDCM.XonChar = 0;
 	ComDCM.XoffChar = 	unsigned char(0xff);
 	ComDCM.fErrorChar = FALSE;
 	ComDCM.fNull = FALSE;
 	ComDCM.fOutxCtsFlow = FALSE;
 	ComDCM.fOutxDsrFlow = FALSE;
 	ComDCM.XonLim = 128;
 	ComDCM.XoffLim = 128;
 
 	if(!SetCommState(m_Handle, &ComDCM)) {
 		CloseHandle(m_Handle);
 		m_Handle = 0;
// 		throw TTYException();
		return false;
 	}
	return true;
 }
 
 void TTY::Disconnect() {
 
 	if(m_Handle != 0) {
 		CloseHandle(m_Handle);
         m_Handle = 0;
 	}
 
 }
 
 void TTY::Write(const vector<	unsigned char>& data) {
	if(data.size()>0)
	{
 		if(m_Handle == 0) {
 			throw TTYException();
 		}
	 
 		DWORD feedback;
 		if(!WriteFile(m_Handle, &data[0], int(data.size()), &feedback, 0) || feedback != int(data.size())) {
 			CloseHandle(m_Handle);
 			m_Handle = 0;
 			throw TTYException();
 		}
	}
 	// In some cases it's worth uncommenting
 	//FlushFileBuffers(m_Handle);
 
 }
 
 bool TTY::Read(vector<	unsigned char>& data) {
 
 	if(m_Handle == 0) {
 		throw TTYException();
 	}
 
 	DWORD begin = GetTickCount();
 	DWORD feedback = 0;
 
 		unsigned char * buf = &data[0];
 	DWORD len = int(data.size());
 
 	int attempts = 1;
 	while(len && (attempts || (GetTickCount()-begin) < DWORD(TIMEOUT/3))) {
 
 		if(attempts) attempts--;
 
 		if(!ReadFile(m_Handle, buf, len, &feedback, NULL)) {
 			CloseHandle(m_Handle);
 			m_Handle = 0;
 			throw TTYException();
 		}
 
 	//test out?	assert(feedback <= len);
 		len -= feedback;
 		buf += feedback;
 
 	}
 
 	if(len) {
		//nothing to read
		if(len== data.size())
		return false;
		else//we read smth, lets check it now
		{
			data.resize(data.size()-len);
			return true;

		}
 	/*	CloseHandle(m_Handle);
 		m_Handle = 0;
 		throw TTYException();*/
 	}
	return true;
 
 }
